/*     */ package com.zimbra.cs.db;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.Metadata;
/*     */ import com.zimbra.cs.volume.Volume;
/*     */ import com.zimbra.cs.volume.Volume.Builder;
/*     */ import com.zimbra.cs.volume.Volume.VolumeMetadata;
/*     */ import com.zimbra.cs.volume.VolumeServiceException;
/*     */ import java.sql.PreparedStatement;
/*     */ import java.sql.ResultSet;
/*     */ import java.sql.SQLException;
/*     */ import java.util.HashMap;
/*     */ import java.util.Map;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class DbVolume
/*     */ {
/*     */   private static final String CN_ID = "id";
/*     */   private static final String CN_TYPE = "type";
/*     */   private static final String CN_NAME = "name";
/*     */   private static final String CN_PATH = "path";
/*     */   private static final String CN_FILE_BITS = "file_bits";
/*     */   private static final String CN_FILE_GROUP_BITS = "file_group_bits";
/*     */   private static final String CN_MAILBOX_BITS = "mailbox_bits";
/*     */   private static final String CN_MAILBOX_GROUP_BITS = "mailbox_group_bits";
/*     */   private static final String CN_COMPRESS_BLOBS = "compress_blobs";
/*     */   private static final String CN_COMPRESSION_THRESHOLD = "compression_threshold";
/*     */   private static final String CN_METADATA = "metadata";
/*     */   
/*     */   public static synchronized Volume create(DbPool.DbConnection conn, Volume volume)
/*     */     throws ServiceException
/*     */   {
/*  55 */     short nextId = volume.getId();
/*  56 */     if (nextId == -1) {
/*  57 */       nextId = getNextVolumeID(conn);
/*     */     }
/*  59 */     if ((nextId <= 0) || (nextId > 255)) {
/*  60 */       throw VolumeServiceException.ID_OUT_OF_RANGE(nextId);
/*     */     }
/*  62 */     PreparedStatement stmt = null;
/*     */     try {
/*  64 */       stmt = conn.prepareStatement("INSERT INTO volume (id, type, name, path, mailbox_group_bits, mailbox_bits, file_group_bits, file_bits, compress_blobs, compression_threshold, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
/*     */       
/*     */ 
/*  67 */       int pos = 1;
/*  68 */       stmt.setShort(pos++, nextId);
/*  69 */       stmt.setShort(pos++, volume.getType());
/*  70 */       stmt.setString(pos++, volume.getName());
/*  71 */       stmt.setString(pos++, volume.getRootPath());
/*  72 */       stmt.setShort(pos++, volume.getMboxGroupBits());
/*  73 */       stmt.setShort(pos++, volume.getMboxBits());
/*  74 */       stmt.setShort(pos++, volume.getFileGroupBits());
/*  75 */       stmt.setShort(pos++, volume.getFileBits());
/*  76 */       stmt.setBoolean(pos++, volume.isCompressBlobs());
/*  77 */       stmt.setLong(pos++, volume.getCompressionThreshold());
/*  78 */       stmt.setString(pos++, volume.getMetadata().toString());
/*  79 */       stmt.executeUpdate();
/*     */     } catch (SQLException e) {
/*  81 */       if (Db.errorMatches(e, Db.Error.DUPLICATE_ROW)) {
/*  82 */         throw VolumeServiceException.ALREADY_EXISTS(nextId, volume.getName(), volume.getRootPath(), e);
/*     */       }
/*  84 */       throw ServiceException.FAILURE("inserting new volume " + nextId, e);
/*     */     }
/*     */     finally {
/*  87 */       DbPool.closeStatement(stmt);
/*     */     }
/*  89 */     return get(conn, nextId);
/*     */   }
/*     */   
/*     */   public static Volume updateMetadata(DbPool.DbConnection conn, short volumeId, Volume.VolumeMetadata volumeMetadata) throws ServiceException {
/*  93 */     PreparedStatement stmt = null;
/*     */     try {
/*  95 */       stmt = conn.prepareStatement("UPDATE volume SET metadata = ? WHERE id = ?");
/*  96 */       int pos = 1;
/*  97 */       stmt.setString(pos++, volumeMetadata.toString());
/*  98 */       stmt.setShort(pos++, volumeId);
/*  99 */       stmt.executeUpdate();
/*     */     } catch (SQLException e) {
/* 101 */       throw ServiceException.FAILURE("updating volume " + volumeId, e);
/*     */     } finally {
/* 103 */       DbPool.closeStatement(stmt);
/*     */     }
/* 105 */     return get(conn, volumeId);
/*     */   }
/*     */   
/*     */   public static Volume update(DbPool.DbConnection conn, Volume volume) throws ServiceException {
/* 109 */     PreparedStatement stmt = null;
/*     */     try {
/* 111 */       stmt = conn.prepareStatement("UPDATE volume SET type = ?, name = ?, path = ?, mailbox_group_bits = ?, mailbox_bits = ?, file_group_bits = ?, file_bits = ?, compress_blobs = ?, compression_threshold = ? , metadata = ? WHERE id = ?");
/*     */       
/*     */ 
/* 114 */       int pos = 1;
/* 115 */       stmt.setShort(pos++, volume.getType());
/* 116 */       stmt.setString(pos++, volume.getName());
/* 117 */       stmt.setString(pos++, volume.getRootPath());
/* 118 */       stmt.setShort(pos++, volume.getMboxGroupBits());
/* 119 */       stmt.setShort(pos++, volume.getMboxBits());
/* 120 */       stmt.setShort(pos++, volume.getFileGroupBits());
/* 121 */       stmt.setShort(pos++, volume.getFileBits());
/* 122 */       stmt.setBoolean(pos++, volume.isCompressBlobs());
/* 123 */       stmt.setLong(pos++, volume.getCompressionThreshold());
/* 124 */       stmt.setString(pos++, volume.getMetadata().toString());
/* 125 */       stmt.setShort(pos++, volume.getId());
/* 126 */       stmt.executeUpdate();
/*     */     } catch (SQLException e) {
/* 128 */       if (Db.errorMatches(e, Db.Error.DUPLICATE_ROW)) {
/* 129 */         throw VolumeServiceException.ALREADY_EXISTS(volume.getId(), volume.getName(), volume.getRootPath(), e);
/*     */       }
/* 131 */       throw ServiceException.FAILURE("updating volume " + volume.getId(), e);
/*     */     }
/*     */     finally {
/* 134 */       DbPool.closeStatement(stmt);
/*     */     }
/* 136 */     return get(conn, volume.getId());
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static boolean delete(DbPool.DbConnection conn, short id)
/*     */     throws ServiceException
/*     */   {
/* 147 */     PreparedStatement stmt = null;
/*     */     try {
/* 149 */       stmt = conn.prepareStatement("DELETE FROM volume WHERE id=?");
/* 150 */       stmt.setShort(1, id);
/* 151 */       int num = stmt.executeUpdate();
/* 152 */       return num == 1;
/*     */     } catch (SQLException e) {
/* 154 */       if (Db.errorMatches(e, Db.Error.FOREIGN_KEY_CHILD_EXISTS)) {
/* 155 */         throw VolumeServiceException.CANNOT_DELETE_VOLUME_IN_USE(id, e);
/*     */       }
/* 157 */       throw ServiceException.FAILURE("deleting volume entry: " + id, e);
/*     */     } finally {
/* 159 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   private static short getNextVolumeID(DbPool.DbConnection conn) throws ServiceException {
/* 164 */     PreparedStatement stmt = null;
/* 165 */     ResultSet rs = null;
/*     */     try {
/* 167 */       stmt = conn.prepareStatement("SELECT MAX(id) FROM volume");
/* 168 */       rs = stmt.executeQuery();
/* 169 */       if (rs.next()) {
/* 170 */         short id = rs.getShort(1);
/* 171 */         id = (short)(id + 1);return id;
/*     */       }
/*     */     } catch (SQLException e) {
/* 174 */       throw ServiceException.FAILURE("getting max volume ID", e);
/*     */     } finally {
/* 176 */       DbPool.closeResults(rs);
/* 177 */       DbPool.closeStatement(stmt);
/*     */     }
/* 179 */     return 1;
/*     */   }
/*     */   
/*     */ 
/*     */   public static Volume get(DbPool.DbConnection conn, short id)
/*     */     throws ServiceException
/*     */   {
/* 186 */     PreparedStatement stmt = null;
/* 187 */     ResultSet rs = null;
/*     */     try {
/* 189 */       stmt = conn.prepareStatement("SELECT * FROM volume WHERE id = ?");
/* 190 */       stmt.setShort(1, id);
/* 191 */       rs = stmt.executeQuery();
/* 192 */       if (rs.next()) {
/* 193 */         return constructVolume(rs);
/*     */       }
/* 195 */       throw VolumeServiceException.NO_SUCH_VOLUME(id);
/*     */     }
/*     */     catch (SQLException e) {
/* 198 */       throw ServiceException.FAILURE("getting volume entry: " + id, e);
/*     */     } finally {
/* 200 */       DbPool.closeResults(rs);
/* 201 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public static Map<Short, Volume> getAll(DbPool.DbConnection conn)
/*     */     throws ServiceException
/*     */   {
/* 209 */     PreparedStatement stmt = null;
/* 210 */     ResultSet rs = null;
/* 211 */     Map<Short, Volume> result = new HashMap();
/*     */     try {
/* 213 */       stmt = conn.prepareStatement("SELECT * FROM volume");
/* 214 */       rs = stmt.executeQuery();
/* 215 */       while (rs.next()) {
/* 216 */         Volume v = constructVolume(rs);
/* 217 */         result.put(Short.valueOf(v.getId()), v);
/*     */       }
/*     */     } catch (SQLException e) {
/* 220 */       throw ServiceException.FAILURE("getting all volume entries", e);
/*     */     } finally {
/* 222 */       DbPool.closeResults(rs);
/* 223 */       DbPool.closeStatement(stmt);
/*     */     }
/* 225 */     return result;
/*     */   }
/*     */   
/*     */   public static class CurrentVolumes {
/* 229 */     public short msgVolId = -2;
/* 230 */     public short secondaryMsgVolId = -2;
/* 231 */     public short indexVolId = -2;
/*     */   }
/*     */   
/*     */   public static CurrentVolumes getCurrentVolumes(DbPool.DbConnection conn) throws ServiceException {
/* 235 */     CurrentVolumes currVols = new CurrentVolumes();
/* 236 */     PreparedStatement stmt = null;
/* 237 */     ResultSet rs = null;
/*     */     try {
/* 239 */       stmt = conn.prepareStatement("SELECT message_volume_id, secondary_message_volume_id, index_volume_id FROM current_volumes");
/* 240 */       rs = stmt.executeQuery();
/* 241 */       if (rs.next()) {
/* 242 */         currVols.msgVolId = rs.getShort(1);
/* 243 */         short s = rs.getShort(2);
/* 244 */         if (!rs.wasNull())
/* 245 */           currVols.secondaryMsgVolId = s;
/* 246 */         currVols.indexVolId = rs.getShort(3);
/*     */       }
/*     */     } catch (SQLException e) {
/* 249 */       throw ServiceException.FAILURE("getting current volumes", e);
/*     */     } finally {
/* 251 */       DbPool.closeResults(rs);
/* 252 */       DbPool.closeStatement(stmt);
/*     */     }
/* 254 */     if ((currVols.msgVolId != -2) && (currVols.indexVolId != -2)) {
/* 255 */       return currVols;
/*     */     }
/* 257 */     return null;
/*     */   }
/*     */   
/*     */   public static void updateCurrentVolume(DbPool.DbConnection conn, short type, short id) throws ServiceException {
/*     */     String col;
/* 262 */     switch (type) {
/*     */     case 1: 
/* 264 */       col = "message_volume_id";
/* 265 */       break;
/*     */     case 2: 
/* 267 */       col = "secondary_message_volume_id";
/* 268 */       break;
/*     */     case 10: 
/* 270 */       col = "index_volume_id";
/* 271 */       break;
/*     */     default: 
/* 273 */       throw new IllegalArgumentException("invalid volume type: " + type);
/*     */     }
/* 275 */     PreparedStatement stmt = null;
/*     */     try {
/* 277 */       stmt = conn.prepareStatement("UPDATE current_volumes SET " + col + " = ?");
/* 278 */       if (id >= 0) {
/* 279 */         stmt.setShort(1, id);
/*     */       } else {
/* 281 */         stmt.setNull(1, -6);
/*     */       }
/* 283 */       stmt.executeUpdate();
/*     */     } catch (SQLException e) {
/* 285 */       throw ServiceException.FAILURE("updating current volume", e);
/*     */     } finally {
/* 287 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   private static Volume constructVolume(ResultSet rs) throws SQLException, ServiceException {
/*     */     Volume.VolumeMetadata metadata;
/*     */     try {
/* 294 */       metadata = new Volume.VolumeMetadata(new Metadata(rs.getString("metadata")));
/*     */     } catch (MailServiceException e) {
/* 296 */       throw VolumeServiceException.INVALID_METADATA(e);
/*     */     } catch (ServiceException e) {
/* 298 */       throw VolumeServiceException.INVALID_METADATA(e);
/*     */     }
/* 300 */     return Volume.builder().setId(rs.getShort("id")).setType(rs.getShort("type")).setName(rs.getString("name")).setPath(Volume.getAbsolutePath(rs.getString("path")), false).setMboxGroupBits(rs.getShort("mailbox_group_bits")).setMboxBit(rs.getShort("mailbox_bits")).setFileGroupBits(rs.getShort("file_group_bits")).setFileBits(rs.getShort("file_bits")).setCompressBlobs(rs.getBoolean("compress_blobs")).setCompressionThreshold(rs.getLong("compression_threshold")).setMetadata(metadata).build();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static boolean isVolumeReferenced(DbPool.DbConnection conn, short volumeId)
/*     */     throws ServiceException
/*     */   {
/* 310 */     PreparedStatement stmt = null;
/* 311 */     ResultSet rs = null;
/*     */     try {
/* 313 */       stmt = conn.prepareStatement("SELECT distinct group_id from mailbox");
/* 314 */       rs = stmt.executeQuery();
/* 315 */       int groupId; while (rs.next()) {
/* 316 */         groupId = rs.getShort(1);
/* 317 */         if (isVolumeReferenced(conn, volumeId, groupId)) {
/* 318 */           return true;
/*     */         }
/*     */       }
/* 321 */       return 0;
/*     */     } catch (SQLException e) {
/* 323 */       throw ServiceException.FAILURE("getting mailbox groups", e);
/*     */     } finally {
/* 325 */       DbPool.closeResults(rs);
/* 326 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   private static boolean isVolumeReferenced(DbPool.DbConnection conn, short volumeId, int groupId) throws ServiceException {
/* 331 */     return (tableRefsVolume(conn, volumeId, groupId, "revision")) || (tableRefsVolume(conn, volumeId, groupId, "revision_dumpster")) || (tableRefsVolume(conn, volumeId, groupId, "mail_item_dumpster")) || (tableRefsVolume(conn, volumeId, groupId, "mail_item"));
/*     */   }
/*     */   
/*     */   private static boolean tableRefsVolume(DbPool.DbConnection conn, short volumeId, int groupId, String table) throws ServiceException
/*     */   {
/* 336 */     PreparedStatement stmt = null;
/* 337 */     ResultSet rs = null;
/*     */     try {
/* 339 */       stmt = conn.prepareStatement("SELECT count(*) from " + DbMailbox.qualifyTableName(groupId, table) + " where locator=?");
/*     */       
/* 341 */       stmt.setInt(1, volumeId);
/* 342 */       rs = stmt.executeQuery();
/* 343 */       return (rs.next()) && (rs.getInt(1) > 0);
/*     */     } catch (SQLException e) {
/* 345 */       throw ServiceException.FAILURE("counting " + table + " refs", e);
/*     */     } finally {
/* 347 */       DbPool.closeResults(rs);
/* 348 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/db/DbVolume.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */